package com.swt.gap.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NetUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.swt.gap.common.PermissionService;
import com.swt.gap.common.constant.CommonConstant;
import com.swt.gap.common.FileTypeEnum;
import com.swt.gap.common.PageResult;
import com.swt.gap.common.constant.GraphDbConstant;
import com.swt.gap.config.ExtractConfig;
import com.swt.gap.config.ServerConfig;
import com.swt.gap.dao.*;
import com.swt.gap.model.dto.*;
import com.swt.gap.model.entity.File;
import com.swt.gap.model.entity.OntologyNode;
import com.swt.gap.model.entity.TaskSubscribeData;
import com.swt.gap.model.entity.TaskSubscribeRule;
import com.swt.gap.model.esdoc.TextFile;
import com.swt.gap.model.params.ElementSameForm;
import com.swt.gap.model.params.UpdateFileParam;
import com.swt.gap.model.vo.*;
import com.swt.gap.model.vo.element.EventElementVO;
import com.swt.gap.model.vo.file.FileInfoVO;
import com.swt.gap.model.vo.file.FileSameElementVO;
import com.swt.gap.model.vo.file.SameElementVO;
import com.swt.gap.service.FileService;
import com.swt.gap.service.FileTask;
import com.swt.gap.service.OntologyNodeService;
import com.swt.gap.util.CsvReader;
import com.swt.gap.util.FileCharsetUtil;
import com.swt.gap.util.UserLoginUtils;
import com.swt.gap.util.excel.ExcelData;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.ooxml.extractor.POIXMLTextExtractor;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.xmlbeans.XmlException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class FileServiceImpl implements FileService {
    private static final int START_INDEX = 0;
    private static final int PREVIEW_NUMBER = 200;

    private static final int TYPE_PREVIEW = 0;


    private final FileDao fileDao;
    private final TaskFileMapper taskFileMapper;
    private final ServerConfig serverConfig;
    private final RestTemplate restTemplate;
    private final ExtractConfig extractConfig;
    private final OntologyNodeService ontologyNodeService;
    private final OntologyNodeDao ontologyNodeDao;
    private final TaskSubscribeRuleDao taskSubscribeRuleDao;
    private final FileClassDao fileClassDao;
    private final TaskSubscribeDataDao taskSubscribeDataDao;
    private final FileTask fileTask;
    private final PermissionService permissionService;
//    private final TextFileDao textFileDao;

    @Value("${server.port}")
    private String port;

    @Value("${is-open-es}")
    private Boolean isOpenEs;

    public FileServiceImpl(FileDao fileDao, TaskFileMapper taskFileMapper, ServerConfig serverConfig,
                           RestTemplate restTemplate, ExtractConfig extractConfig,
                           OntologyNodeService ontologyNodeService,
                           OntologyNodeDao ontologyNodeDao,
                           TaskSubscribeRuleDao taskSubscribeRuleDao,
                           FileClassDao fileClassDao,
                           TaskSubscribeDataDao taskSubscribeDataDao,
                           FileTask fileTask,
                           PermissionService permissionService/*,
                           TextFileDao textFileDao*/) {
        this.fileDao = fileDao;
        this.taskFileMapper = taskFileMapper;
        this.serverConfig = serverConfig;
        this.restTemplate = restTemplate;
        this.extractConfig = extractConfig;
        this.ontologyNodeService = ontologyNodeService;
        this.ontologyNodeDao = ontologyNodeDao;
        this.taskSubscribeRuleDao = taskSubscribeRuleDao;
        this.fileClassDao = fileClassDao;
        this.taskSubscribeDataDao = taskSubscribeDataDao;
        this.fileTask = fileTask;
        this.permissionService = permissionService;
//        this.textFileDao = textFileDao;
    }


    /*@Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addNewFile(UploadFileVO.FileInfo fileInfo, int fileClassId, Boolean repeat) {
        //获取创建者信息
        int userId = UserLoginUtils.getUser().getUserId();
        File file = new File();
        file.setCreatedBy(userId);
        file.setCreatedTime(new Date());
        file.setFileName(fileInfo.getOriginalFileName());
        file.setFileSize(fileInfo.getSize());
        file.setFileType(fileInfo.getTypeCode());
        file.setFileClassId(fileClassId);
        file.setIsDeleted(repeat);

        //数据来源
        file.setFileFromType(2);
        file.setSaveName(fileInfo.getSaveFileName());
        file.setSavePath(CommonConstant.RELATIVE_DIR + fileInfo.getSaveFileName());
        fileMapper.insertSelective(file);
        return file.getFileId();
    }*/

    @Override
    public Integer addFile(File file) {
        int userId = UserLoginUtils.getUser().getUserId();

        file.setCreatedBy(userId);
        file.setCreatedTime(new Date());
        file.setIsDeleted(false);
        //数据来源
        file.setFileFromType(2);
        fileDao.insertSelective(file);

        return file.getFileId();
    }

    @Override
    public PageResult<TaskFileVO> getTaskFileByKey(Integer taskId, String keyword, Integer pageNum, Integer pageSize) {
        //判断页数
        if (null == pageNum || pageNum < 1) {
            pageNum = 1;
        }
        if (null == pageSize || pageSize < 1) {
            pageNum = 10;
        }
        //分页
        PageHelper.startPage(pageNum, pageSize);
        Page<TaskFileVO> taskFilePage = taskFileMapper.getTaskFileVOsByKeyword(taskId, keyword);
        return new PageResult<>(taskFilePage);
    }


    @Override
    public Integer updateSameFile(UploadFileVO.FileInfo fileInfo, Integer fileId) {
        File newFile = new File();
        newFile.setFileId(fileId);
//        newFile.setSavePath(CommonConstant.UPLOAD_DIR + fileInfo.getSaveFileName());
        newFile.setSavedFileName(fileInfo.getSavedFileName());
        newFile.setFileSize(fileInfo.getFileSize());
        newFile.setCreatedTime(new Date());
        return fileDao.updateByPrimaryKeySelective(newFile);
    }

    @Override
    public Integer deleteSuccessFile(Integer fileId) {
        File file = fileDao.selectByPrimaryKey(fileId);
        java.io.File saveFile = new java.io.File(CommonConstant.UPLOAD_DIR + file.getSavedFileName());
        if (saveFile.exists()) {
            saveFile.delete();
        }
        return fileDao.deleteByPrimaryKey(fileId);
    }

    @Override
    public File getFileByid(Integer fileId) {
        return fileDao.selectByPrimaryKey(fileId);
    }

    @Override
    public UploadFileVO coverFile(String savedFileName, Double fileSize, Integer oldFileId) {
        UploadFileVO uploadFileVO = new UploadFileVO();
        File record = fileDao.selectByPrimaryKey(oldFileId);
        /*//先删除之前的重名数据
        java.io.File file = new java.io.File(System.getProperty("user.dir") + record.getSavePath());
        if (file.exists()) {
            file.delete();
        }*/
        record.setSavedFileName(savedFileName);
        record.setFileSize(fileSize);
        fileDao.updateByPrimaryKeySelective(record);
//        fileMapper.deleteByPrimaryKey(oldFileId);

//        fileMapper.activeFile(fileId);

//        File newRecord = fileMapper.selectByPrimaryKey(fileId);
        uploadFileVO.setFileId(oldFileId);
        uploadFileVO.setUploadSuccess(true);
        UploadFileVO.FileInfo fileInfo = new UploadFileVO.FileInfo();
        fileInfo.setOriginalFileName(record.getOriginalFileName());
        fileInfo.setSavedFileName(record.getSavedFileName());
        fileInfo.setFileSize(record.getFileSize());
        fileInfo.setFileType(record.getFileType());
        uploadFileVO.setSuccessFile(fileInfo);
        return uploadFileVO;

    }

    @Override
    public UploadFileVO uploadRepeatFile(String fileName, Integer fileId) {
        UploadFileVO uploadFileVO = new UploadFileVO();
        Integer userId = UserLoginUtils.getUser().getUserId();
        File newRecord = fileDao.selectByPrimaryKey(fileId);
        //对新名字进行字数判断
        String newFileName = fileName.substring(0, fileName.lastIndexOf("."));
        //文件名超过20个字符则截取前20个字符
        newFileName = newFileName.trim();
        if (newFileName.length() > 20) {
            newFileName = newFileName.substring(0, 20);
        }
        String extension = fileName.substring(fileName.lastIndexOf("."));
        newFileName = newFileName + extension;

        List<File> file = fileDao.selectSameFile(newFileName, newRecord.getFileType(), newRecord.getFileClassId(), userId);
        //判断是否还重名
        if (file != null && !file.isEmpty()) {
            uploadFileVO.setUploadSuccess(false);
            uploadFileVO.setFileId(fileId);
            uploadFileVO.setOldFileId(file.get(0).getFileId());
            UploadFileVO.FailedFile failedFile = new UploadFileVO.FailedFile();
            failedFile.setErrorCode(4);
            failedFile.setErrorMessage("该数据源名称已存在");
            failedFile.setFailedFileName(fileName);
            uploadFileVO.setFailedFile(failedFile);
            return uploadFileVO;
        }

        newRecord.setOriginalFileName(newFileName);
        newRecord.setIsDeleted(false);
        fileDao.updateByPrimaryKeySelective(newRecord);
        uploadFileVO.setFileId(fileId);
        uploadFileVO.setUploadSuccess(true);
        UploadFileVO.FileInfo fileInfo = new UploadFileVO.FileInfo();
        fileInfo.setFileType(newRecord.getFileType());
        fileInfo.setFileSize(newRecord.getFileSize());
        fileInfo.setSavedFileName(newRecord.getSavedFileName());
        fileInfo.setOriginalFileName(newFileName);
        uploadFileVO.setSuccessFile(fileInfo);
        return uploadFileVO;
    }

    @Override
    public UrlVO getUrlByFileId(Integer fileId) {
        String saveName = fileDao.selectByPrimaryKey(fileId).getSavedFileName();
        //String ip =InetAddress.getLocalHost().getHostAddress()
        String ip = NetUtil.getLocalhostStr();
        String url = "http://" + ip + ":" + port + "/" + saveName;
        UrlVO urlVO = new UrlVO();
        urlVO.setUrl(url);
        return urlVO;
    }

    @Override
    public Integer deleteBatchFile(List<Integer> fileIds) {
        //删除和该数据源有关联的任务数据
        taskFileMapper.deleteByFileIds(fileIds);
        return fileDao.deleteBatch(fileIds);
    }

    @Override
    public FileInfoVO getFileInfo(Integer fileId, Integer viewType) {
        FileInfoVO fileInfoVO = new FileInfoVO();
        File file = fileDao.selectByPrimaryKey(fileId);
        if (null == file) {
            return null;
        }
        Integer fileType = file.getFileType();


        fileInfoVO.setFileName(file.getOriginalFileName());
        BeanUtils.copyProperties(file, fileInfoVO);
        String filePath = CommonConstant.UPLOAD_DIR + file.getSavedFileName();
        if (FileTypeEnum.AVI.getDataTypeCode().equals(fileType)) {
            //媒体数据，返回链接
            fileInfoVO.setData(serverConfig.parseViewUrl(file.getSavedFileName(), 1));
        } else if (FileTypeEnum.CSV.getDataTypeCode().equals(fileType)) {
            //表单数据
            FormDataVO formDataVO;
            if (filePath.endsWith(FileTypeEnum.CSV.getSuffix())) {
                formDataVO = getCsvData(filePath, viewType);

            } else {
                formDataVO = getExcelData(filePath, viewType);
            }

            fileInfoVO.setData(JSON.toJSONString(formDataVO));
        } else if (FileTypeEnum.TXT.getDataTypeCode().equals(fileType)) {
            //文本文件
            String textData;
            if (filePath.endsWith(FileTypeEnum.TXT.getSuffix())) {
                textData = getTextData(filePath);
            } else {
                textData = getWordData(filePath);
            }
            fileInfoVO.setData(textData);
        }
        Integer loginUserId = UserLoginUtils.getUserId();
        fileInfoVO.setHasWritePermission(permissionService.hasWritePerm(loginUserId, file.getCreatedBy()));
        return fileInfoVO;
    }

    @Override
    public PageResult<FileSameElementVO> getFileSameElements(Integer fileId, Integer page, Integer size, List<ElementSameForm> elementIds) {
        List<FileSameElementVO> rets = new ArrayList<>();
        File file = fileDao.selectByPrimaryKey(fileId);
        JSONObject textElement = file.getTextElement();
        //且
        Boolean and = true;


//        List<FileElementsEntities> allElements = fileMapper.getAllElements(fileId);

//        if(CollUtil.isEmpty(allElements)){
//            return null;
//        }
//        for (FileElementsEntities elements : allElements) {
//            Integer fileId1 = elements.getFileId();
//        }
//        FileElementsEntities allElement = fileMapper.getOneElements(fileId);

        JSONArray eventElements = textElement.getJSONArray("eventElements");


        //指定的要素

        Map<Integer, Set<String>> elements = new HashMap<>();
        //比对的要素
        Map<Integer, Set<String>> elementsComparison = new HashMap<>();
        for (int i = 0; i < eventElements.size(); i++) {
            Integer elementId = eventElements.getJSONObject(i).getInteger("elementId");
            JSONArray elementTexts = eventElements.getJSONObject(i).getJSONArray("elementTexts");
            Set<String> textAll = new HashSet<>();
            for (int j = 0; j < elementTexts.size(); j++) {
                JSONObject o = elementTexts.getJSONObject(j);
                String text = o.getString("text");
                textAll.add(text);
            }
            if (CollUtil.isEmpty(textAll)) {
                continue;
            }
            elementsComparison.put(i, textAll);
        }
        if (CollUtil.isNotEmpty(elementIds)) {
            //要匹配的要素id
            List<Integer> elementSearchIds = new ArrayList<>();
            elementIds.stream().forEach(elementSameForm -> {
                elementSearchIds.add(elementSameForm.getElementId());
            });
            for (int i = 0; i < eventElements.size(); i++) {
                Integer elementId = eventElements.getJSONObject(i).getInteger("elementId");
                for (ElementSameForm elementSameForm : elementIds) {
                    Integer elementId1 = elementSameForm.getElementId();
                    if (elementId1.equals(elementId)) {
                        elements.put(i, elementSameForm.getTexts());
                    }
                }


            }
        } else {
            //默认情况 任一要素都行
            and = false;

//            Integer nodeId = null;
//            if (null != textElement) {
//                nodeId = textElement.getInteger("eventOntologyNodeId");
//            } else {
//                return null;
//            }
//            String eventOntologyNodeName = textElement.getString("eventOntologyNodeName");
//            List<EventElementVO> eventRelElementsOntology = ontologyNodeService.listEventElementsAndRelNodeById(nodeId);
            for (int i = 0; i < eventElements.size(); i++) {
                //todo 排除不要的要素
                Integer elementId = eventElements.getJSONObject(i).getInteger("elementId");
                JSONArray elementTexts = eventElements.getJSONObject(i).getJSONArray("elementTexts");
                if (CollUtil.isNotEmpty(elementTexts)) {
                    Set<String> texts = new HashSet<>();
                    for (int j = 0; j < elementTexts.size(); j++) {
                        String o = elementTexts.getJSONObject(j).getString("text");
                        texts.add(o);
                    }
                    elements.put(i, texts);
                }
            }


        }
        //所有指定同要素的文档

        Set<Integer> fileIds = new HashSet<>();
        for (Integer index : elements.keySet()) {


            Set<String> elementTexts = elements.get(index);
            if (CollUtil.isEmpty(elementTexts)) {
                continue;
            }


            Iterator<String> iterator1 = elementTexts.iterator();
            while (iterator1.hasNext()) {
                String text = iterator1.next();
                //该要素匹配的文档
                List<Integer> containElements = fileDao.getContainElements(fileId, text, index);
                if (and) {
                    //且
                    if (CollUtil.isEmpty(containElements)) {
                        //返回空
                        return null;
                    } else {
                        if (CollUtil.isEmpty(fileIds)) {
                            fileIds.addAll(containElements);
                        } else {
                            Set<Integer> newIds = new HashSet<>();
                            for (Integer fileIdOther : containElements) {
                                if (fileIds.contains(fileIdOther)) {
                                    newIds.add(fileIdOther);
                                }
                            }
                            if (CollUtil.isEmpty(newIds)) {
                                return null;
                            } else {
                                fileIds = newIds;
                            }
                        }
                    }
                } else {
                    //或
                    fileIds.addAll(containElements);
                }
            }
        }
        List<Integer> allFileIds = new ArrayList<>();
        allFileIds.addAll(fileIds);
        Collections.sort(allFileIds, Collections.reverseOrder());
        if (allFileIds.size() >= page * size) {
            allFileIds = allFileIds.subList((page - 1) * size, page * size - 1);
        }
        for (Integer id : allFileIds) {
            FileInfoVO fileInfo = getFileInfo(id, 0);
            FileSameElementVO fileSameElementVO = new FileSameElementVO();
            BeanUtils.copyProperties(fileInfo, fileSameElementVO);
            JSONObject textElementOther = fileSameElementVO.getTextElement();
            JSONArray eventElementsOther = textElementOther.getJSONArray("eventElements");
            List<SameElementVO> sameElementArray = new ArrayList<>();
            for (Integer i : elementsComparison.keySet()) {
                if (eventElementsOther.size() <= i) {
                    break;
                }
                JSONObject eventElementOther = eventElementsOther.getJSONObject(i);
                Set<String> strings = elementsComparison.get(i);
                Set<String> list = new HashSet<>();
                JSONArray elementTexts = eventElementOther.getJSONArray("elementTexts");
                for (int j = 0; j < elementTexts.size(); j++) {
                    String o = elementTexts.getJSONObject(j).getString("text");
                    if (strings.contains(o)) {
                        list.add(o);
                    }
                }
                if (CollUtil.isNotEmpty(list)) {
                    SameElementVO oneSameElement = new SameElementVO();
                    oneSameElement.setName("同".concat(eventElementOther.getString("element")));
                    oneSameElement.setElements(list);
                    sameElementArray.add(oneSameElement);
                }
            }
            fileSameElementVO.setSameElements(sameElementArray);
            rets.add(fileSameElementVO);
        }


        return new PageResult<FileSameElementVO>(rets, fileIds.size(), size, page);
    }

   /* @Override
    public Boolean saveFileInfo(List<FileMetaInfo> fileInfos) {

        for (FileMetaInfo fileInfo : fileInfos) {
            fileTask.saveFile(fileInfo);

        }
        return true;
    }*/


    @Override
    public Boolean saveFileInfo(List<FileMetaInfo> fileInfos) {
        Integer loginUserId = UserLoginUtils.getUserId();
        //将数据信息新增到数据库
        ExecutorService executorService = new ThreadPoolExecutor(20, 40, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy());
        CountDownLatch countDownLatch = new CountDownLatch(fileInfos.size());
        for (FileMetaInfo fileInfo : fileInfos) {

            executorService.execute(() -> {
                try {
                    log.info("处理文件：" + fileInfo.getOriginalFileName());
                    File file = new File();
                    BeanUtils.copyProperties(fileInfo, file);

                    String path = CommonConstant.UPLOAD_DIR + fileInfo.getSavedFileName();
                    String content = "";
                    if (path.endsWith(FileTypeEnum.TXT.getSuffix())) {
                        content = getTextData(path);
                    } else {
                        content = getWordData(path);
                    }
                    EventExtractVO eventExtractVO = null;
                    if (StringUtils.hasLength(content)) {
                        eventExtractVO = parseElement(fileInfo.getOriginalFileName(), content);
                        file.setTextElement((JSONObject) JSON.toJSON(eventExtractVO));
                    }
                    addFile(file);
                    if (isOpenEs) {
                        addFileToEs(file.getFileId(), content, eventExtractVO);
                    }
                    Optional.ofNullable(eventExtractVO).ifPresent(e -> fileTask.checkSubscribe(file, e, loginUserId));
                } catch (Exception e) {
                    log.error("保存文件出错", e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }

        try {
            // 等待完毕
            countDownLatch.await();
        } catch (Exception e) {
            log.error("保存文件错误", e);
        } finally {
            // 关闭线程池
            executorService.shutdown();
        }
        return true;
    }

    @Override
    public Boolean saveFileInfo(SaveFileInfoVO record) {
        List<FileMetaInfo> fileInfos = record.getFileMetaInfos();
        fileInfos.forEach(file -> file.setPassword(record.getPassword()));
        return saveFileInfo(fileInfos);
    }


    private FormDataVO getCsvData(String filePath, Integer viewType) {
        CsvReader iTextReader = new CsvReader(filePath);
        FormDataVO formDataVO = new FormDataVO();
        formDataVO.setHeader(iTextReader.getHeader());
        List<List<String>> values;
        if (TYPE_PREVIEW == viewType) {
            //预览数据
            values = iTextReader.getSamplesWithoutHead(START_INDEX, START_INDEX + PREVIEW_NUMBER);
        } else {
            values = iTextReader.getDataWithoutHead();
        }
        formDataVO.setRows(values);
        return formDataVO;
    }

    private FormDataVO getExcelData(String filePath, Integer viewType) {
        ExcelData excelData;
        if (TYPE_PREVIEW == viewType) {
            excelData = com.swt.gap.util.excel.ExcelUtil.getReader().read(filePath, START_INDEX, START_INDEX + PREVIEW_NUMBER);

        } else {
            excelData = com.swt.gap.util.excel.ExcelUtil.getReader().read(filePath);
        }
        return new FormDataVO(excelData.getHeader(), excelData.getRows());
    }

    private String getWordData(String filePath) {
        String wordData = "";
        try {
            if (filePath.endsWith(FileTypeEnum.WORD03.getSuffix())) {
                FileInputStream fis = new FileInputStream(filePath);
                WordExtractor wordExtractor = new WordExtractor(fis);
                wordData = wordExtractor.getText();

            } else if (filePath.endsWith(FileTypeEnum.WORD07.getSuffix())) {
                OPCPackage opcPackage = POIXMLDocument.openPackage(filePath);
                POIXMLTextExtractor extractor = new XWPFWordExtractor(opcPackage);
                wordData = extractor.getText();
            }
        } catch (IOException | XmlException | OpenXML4JException e) {
            e.printStackTrace();
        }

        return wordData;

    }

    private String getTextData(String filePath) {
        StringBuilder fileContent = new StringBuilder();
        String fileCharset = FileCharsetUtil.getFilecharset(new java.io.File(filePath));
        BufferedReader br = null;
        try {
            InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), fileCharset);
            br = new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null) {
                line += '\n';
                fileContent.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return fileContent.toString();

    }

    @Override
    public EventExtractVO parseElement(String originalFileName, String text) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HashMap<String, Object> requestBody = new HashMap<>();
            // id为任意字符串，用来区分不同的请求
            requestBody.put("id", new Random(1).nextInt(100));
            requestBody.put("text", text);
            List<String> tasks = Arrays.asList("entity", "time_space", "subject_event", "event");
            requestBody.put("tasks", tasks);
            HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(requestBody, headers);

            // 事件类型
            EventClassDTO eventClassDTO = restTemplate.postForEntity(extractConfig.getEventClass(), httpEntity, EventClassDTO.class).getBody();

            // 事件要素
            EventElementParsDTO eventElementParsDTO = restTemplate.postForEntity(extractConfig.getElement(), httpEntity, EventElementParsDTO.class).getBody();

            String labels = Objects.requireNonNull(eventClassDTO).getResults();
            if (labels.contains("-")) {
                labels = labels.substring(labels.indexOf("-") + 1);
            }
            List<OntologyNode> ontologyNodes = ontologyNodeDao.selectByLabels("事件," + labels);
            if (!CollectionUtils.isEmpty(ontologyNodes)) {
                int nodeId = ontologyNodeDao.selectByLabels("事件," + labels).get(0).getNodeId();
                List<EventElementVO> eventRelElementsOntology = ontologyNodeService.listEventElementsAndRelNodeById(nodeId);
                assert eventElementParsDTO != null;
                List<ElementValueDTO> eventElements = new ArrayList<>();
                for (EventElementVO eventElement : eventRelElementsOntology) {
                    ElementValueDTO elementValue = new ElementValueDTO();
                    BeanUtils.copyProperties(eventElement, elementValue);
                    List<TextIndex> elements = new ArrayList<>();
                    for (EventElementParsDTO.ResultsDTO.ParsDTO par : eventElementParsDTO.getResults().getPars()) {
                        int parStartIndex = par.getParBegin();
                        for (EventElementParsDTO.ResultsDTO.ParsDTO.SentsDTO sent : par.getSents()) {
                            int sentStartIndex = sent.getSentBegin();
                            for (EventElementParsDTO.ResultsDTO.ParsDTO.SentsDTO.PredEntityMentionsDTO entity : sent.getPredEntityMentions()) {
                                // 临时帮南大把“武器” 改成“装备”
                                if ("武器".equals(entity.getSubtypeCn())) {
                                    entity.setSubtypeCn("装备");
                                }

                                if (entity.getSubtypeCn().equals(eventElement.getElement())) {
                                    TextIndex textIndex = TextIndex.builder()
                                            .text(entity.getText())
                                            .startIndex(parStartIndex + sentStartIndex + entity.getBegin())
                                            .endIndex(parStartIndex + sentStartIndex + entity.getEnd())
                                            .build();
                                    elements.add(textIndex);
                                }
                            }
                            for (EventElementParsDTO.ResultsDTO.ParsDTO.SentsDTO.PredTimeSpaceMentionsDTO timeSpace : sent.getPredTimeSpaceMentions()) {
                                if (timeSpace.getTypeCn().equals(eventElement.getElement())) {
                                    TextIndex textIndex = TextIndex.builder()
                                            .text(timeSpace.getText())
                                            .startIndex(parStartIndex + sentStartIndex + timeSpace.getBegin())
                                            .endIndex(parStartIndex + sentStartIndex + timeSpace.getEnd())
                                            .build();
                                    elements.add(textIndex);
                                }
                                if ("时间".equals(timeSpace.getTypeCn()) && "开始时间".equals(eventElement.getElement())) {
                                    TextIndex textIndex = TextIndex.builder()
                                            .text(timeSpace.getNormalization())
                                            .startIndex(parStartIndex + sentStartIndex + timeSpace.getBegin())
                                            .endIndex(parStartIndex + sentStartIndex + timeSpace.getEnd())
                                            .build();
                                    elements.add(textIndex);
                                }
                            }

                        }
                    }
                    // 事件描述，全文
                    if (elementValue.getElement().equals(GraphDbConstant.PROPERTY_KEY_DESCRIPTION)) {
                        elements.add(new TextIndex(0, 0, text));
                    }

                    if (elementValue.getElement().equals(GraphDbConstant.PROPERTY_KEY_NAME)
                            && elements.isEmpty()) {
                        if (null != originalFileName) {
                            elements.add(new TextIndex(0, 0, originalFileName.substring(0, originalFileName.indexOf("."))));
                        } else {
                            String name = text;
                            if (name.contains("。")) {
                                name = name.substring(0, name.indexOf("。"));
                            }
                            if (name.contains("，")) {
                                name = name.substring(0, name.indexOf("，"));
                            }
                            elements.add(new TextIndex(0, 0, name));
                        }
                    }
                    elementValue.setElementTexts(elements);
                    eventElements.add(elementValue);
                }

                eventElements.forEach(eventElement -> {
//                    List<TextIndex> elementTexts = new ArrayList<>();
                    Map<String, List<TextIndex>> mapText = eventElement.getElementTexts().stream()
                            .collect(Collectors.groupingBy(TextIndex::getText));

                });

                // 移除地点里的 军事基地
                List<TextIndex> bases = new ArrayList<>();
                eventElements.forEach(eventElement -> {
                    if ("军事基地".equals(eventElement.getElement())) {
                        bases.addAll(eventElement.getElementTexts());
                    }

                });
                eventElements.forEach(eventElement -> {
                    if ("地点 ".equals(eventElement.getElement())) {
                        List<TextIndex> elementTexts = new ArrayList<>();
                        eventElement.getElementTexts().forEach(elementText -> {
                            if (!bases.contains(elementText)) {
                                elementTexts.add(elementText);
                            }
                        });
                        eventElement.setElementTexts(elementTexts);
                    }

                });
                return EventExtractVO.builder()
                        .eventOntologyNodeName(labels)
                        .eventOntologyNodeId(nodeId)
                        .eventElements(eventElements)
                        .build();
            } else {
                return new EventExtractVO();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new EventExtractVO();
        }
    }
    @Override
    public EventExtractVO parseElementNew(String originalFileName, String text) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HashMap<String, Object> requestBody = new HashMap<>();
            // id为任意字符串，用来区分不同的请求
            requestBody.put("id", new Random(1).nextInt(100));
            requestBody.put("text", text);
            List<String> tasks = Arrays.asList("entity", "time_space", "subject_event", "event");
            requestBody.put("tasks", tasks);
            HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(requestBody, headers);
            EventClassNewDTO eventClassDTO2 = restTemplate.postForEntity(extractConfig.getElementNew(), httpEntity, EventClassNewDTO.class).getBody();
            EventClassNewDTO.ResultsDTO resultsX = eventClassDTO2.getResultsX();
            if (null != resultsX) {
                EventClassNewDTO.ResultsDTO.PredSubjectEventDTO predSubjectEvent = resultsX.getPredSubjectEvent();
                String labels = predSubjectEvent.getType();
                if (StrUtil.isNotBlank(labels)) {
                    labels = labels.substring(labels.indexOf("-") + 1);
                    List<OntologyNode> ontologyNodes = ontologyNodeDao.selectByLabels("事件," + labels);
                    if (!CollectionUtils.isEmpty(ontologyNodes)) {
                        int nodeId = ontologyNodeDao.selectByLabels("事件," + labels).get(0).getNodeId();
                        List<EventElementVO> eventRelElementsOntology = ontologyNodeService.listEventElementsAndRelNodeById(nodeId);
                        assert eventClassDTO2 != null;
                        List<ElementValueDTO> eventElements = new ArrayList<>();
                        for (EventElementVO eventElement : eventRelElementsOntology) {
                            String englishName = eventElement.getEnglishName();
                            ElementValueDTO elementValue = new ElementValueDTO();
                            BeanUtils.copyProperties(eventElement, elementValue);
                            List<TextIndex> elements = new ArrayList<>();
                            List<EventClassNewDTO.ResultsDTO.PredEntityDTO> predEntity = resultsX.getPredEntity();
                            List<EventClassNewDTO.ResultsDTO.PredTimeSpaceDTO> predTimeSpace = resultsX.getPredTimeSpace();
                            for (EventClassNewDTO.ResultsDTO.PredTimeSpaceDTO timeSpaceDTO : predTimeSpace) {
                                String type = timeSpaceDTO.getType();
                                type = type.split("-")[0];
                                if(type.equals(englishName)){
                                    List<EventClassNewDTO.ResultsDTO.PredTimeSpaceDTO.TimeSpaceMentionsDTO> timeSpaceMentions = timeSpaceDTO.getTimeSpaceMentions();
                                    timeSpaceMentions.stream().forEach(timeSpaceMentionsDTO -> {
                                        Integer begin = timeSpaceMentionsDTO.getDocBegin();
                                        Integer docEnd = timeSpaceMentionsDTO.getDocEnd();
                                        String normalization = timeSpaceMentionsDTO.getNormalization();
                                        TextIndex textIndex = TextIndex.builder()
                                                .text(normalization)
                                                .startIndex(begin)
                                                .endIndex(docEnd)
                                                .build();
                                        elements.add(textIndex);
                                    });


                                }
                            }
                            for (EventClassNewDTO.ResultsDTO.PredEntityDTO par : predEntity) {
                                String type = par.getType();
                                type = type.split("-")[0];
                                if (type.equals(englishName)) {
                                    List<EventClassNewDTO.ResultsDTO.PredEntityDTO.EntityMentionsDTO> entityMentions = par.getEntityMentions();
                                    entityMentions.stream().forEach(entityMentionsDTO -> {
                                        Integer begin = entityMentionsDTO.getDocBegin();
                                        Integer docEnd = entityMentionsDTO.getDocEnd();
                                        String normalization = entityMentionsDTO.getNormalization();
                                        TextIndex textIndex = TextIndex.builder()
                                                .text(normalization)
                                                .startIndex(begin)
                                                .endIndex(docEnd)
                                                .build();
                                        elements.add(textIndex);
                                    });
                                }

                            }
                            // 事件描述，全文
                            if (elementValue.getElement().equals(GraphDbConstant.PROPERTY_KEY_DESCRIPTION)) {
                                elements.add(new TextIndex(0, 0, text));
                            }

                            if (elementValue.getElement().equals(GraphDbConstant.PROPERTY_KEY_NAME)
                                    && elements.isEmpty()) {
                                if (null != originalFileName) {
                                    elements.add(new TextIndex(0, 0, originalFileName.substring(0, originalFileName.indexOf("."))));
                                } else {
                                    String name = text;
                                    if (name.contains("。")) {
                                        name = name.substring(0, name.indexOf("。"));
                                    }
                                    if (name.contains("，")) {
                                        name = name.substring(0, name.indexOf("，"));
                                    }
                                    elements.add(new TextIndex(0, 0, name));
                                }
                            }
                            elementValue.setElementTexts(elements);
                            eventElements.add(elementValue);
                        }

                        eventElements.forEach(eventElement -> {
//                    List<TextIndex> elementTexts = new ArrayList<>();
                            Map<String, List<TextIndex>> mapText = eventElement.getElementTexts().stream()
                                    .collect(Collectors.groupingBy(TextIndex::getText));

                        });

                        // 移除地点里的 军事基地
                        List<TextIndex> bases = new ArrayList<>();
                        eventElements.forEach(eventElement -> {
                            if ("军事基地".equals(eventElement.getElement())) {
                                bases.addAll(eventElement.getElementTexts());
                            }

                        });
                        eventElements.forEach(eventElement -> {
                            if ("地点 ".equals(eventElement.getElement())) {
                                List<TextIndex> elementTexts = new ArrayList<>();
                                eventElement.getElementTexts().forEach(elementText -> {
                                    if (!bases.contains(elementText)) {
                                        elementTexts.add(elementText);
                                    }
                                });
                                eventElement.setElementTexts(elementTexts);
                            }

                        });
                        return EventExtractVO.builder()
                                .eventOntologyNodeName(labels)
                                .eventOntologyNodeId(nodeId)
                                .eventElements(eventElements)
                                .build();
                    } else {
                        return new EventExtractVO();
                    }
                }

            }



        } catch (Exception e) {
            e.printStackTrace();
            return new EventExtractVO();
        }
        return null;
    }

    @Async
    public void checkSubscribe(File file, EventExtractVO eventExtract) {
        List<TaskSubscribeRule> taskSubscribeRules = taskSubscribeRuleDao.selectAll();
        taskSubscribeRules.forEach(taskSubscribeRule -> {
            boolean isMatch = false;
            List<SubscribeRuleDTO> subscribeRules = JSONObject.parseArray(taskSubscribeRule.getRule().toJSONString(), SubscribeRuleDTO.class);
            for (SubscribeRuleDTO rule : subscribeRules) {
                boolean isMatchEvent = rule.getOntologyNodeName().equals(eventExtract.getEventOntologyNodeName());
                boolean hasElementRule = null != rule.getElements() && !rule.getElements().isEmpty();
                if (isMatchEvent && !hasElementRule) {
                    isMatch = true;
                    break;
                } else if (isMatchEvent) {
                    List<ElementSubscribeDTO> elementSubscribeRules = rule.getElements();
                    isMatch = elementSubscribeRules.stream()
                            .anyMatch(elementSubscribeRule -> eventExtract.getEventElements().stream()
                                    .anyMatch(elementValue -> {
                                        boolean isMatchElementType = elementValue.getElement().equals(elementSubscribeRule.getElement());
                                        boolean isMatchElementValue = elementValue.getElementTexts().stream()
                                                .anyMatch(textIndex -> textIndex.getText().equals(elementSubscribeRule.getSubscribeValue()));
                                        return isMatchElementType && isMatchElementValue;
                                    })
                            );
                    if (isMatch) {
                        break;
                    }
                    /*for (ElementSubscribeDTO elementSubscribeRule : elementSubscribeRules) {
                        if (isMatch) {
                            break;
                        }
                        for(ElementValueDTO elementValue : eventExtract.getEventElements()) {
                            if (isMatch) {
                                break;
                            }
                            if (elementSubscribeRule.getElement().equals(elementValue.getElement())) {
                                for (TextIndex text : elementValue.getElementTexts()) {
                                    if (elementSubscribeRule.getSubscribeValue().equals(text.getText())) {
                                        isMatch = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }*/
                }
            }
            if (isMatch) {
                String fileClassName = fileClassDao.selectByPrimaryKey(file.getFileClassId()).getClassName();
                SubscribeFileDTO subscribeFile = SubscribeFileDTO.builder()
                        .fileClassName(fileClassName)
                        .build();
                file.setTextElement(null);
                BeanUtils.copyProperties(file, subscribeFile);

                TaskSubscribeData taskSubscribeData = TaskSubscribeData.builder()
                        .taskId(taskSubscribeRule.getTaskId())
                        .fileId(file.getFileId())
                        .fileContent(JSON.toJSONString(subscribeFile))
                        .status(1)
                        .createdTime(new Date())
                        .build();
                taskSubscribeDataDao.insertSelective(taskSubscribeData);
            }
        });
    }

    @Override
    public Boolean isExistsFileName(String fileName, Integer fileClassId, Integer fileType) {
        Integer userId = UserLoginUtils.getUser().getUserId();
        //判断该用户是否上传了重名数据
        List<com.swt.gap.model.entity.File> record = fileDao.selectSameFile(fileName,
                fileType, fileClassId, userId);
        //有重名数据
        return record != null && !record.isEmpty();
    }

    @Override
    public Integer updateFileTextElement(UpdateFileParam record) {
        File file = new File();
        BeanUtils.copyProperties(record, file);
        return fileDao.updateByPrimaryKeySelective(file);
    }

    @Async
    public void addFileToEs(Integer fileId, String content, EventExtractVO textElement) {
        if (isOpenEs) {
            TextFile textFile = TextFile.builder()
                    .fileId(fileId)
                    .fileContent(content)
                    .textElement(textElement)
                    .build();
//            textFileDao.save(textFile);
        }
    }
}
